package SpLib.Net
{
	import flash.display.Loader;
	import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.TimerEvent;
	import flash.net.URLRequest;
	import flash.utils.Timer;
	
	public class NetLoader extends EventDispatcher
	{
		/** 加载到子域 */
        public static const TARGET_CHILD : String = "child";
        /** 加载到同域 */
        public static const TARGET_SAME : String = "same";
        /** 加载到新域 */
        public static const TARGET_NEW : String = "new";
        
		public static const DEF_MAX_RET_TIMES:int = 3;
		public static const DEF_MAX_TIMEOUT:int = 3000;
		
		private var m_sDownUrl:String = "";
		
		private var m_nRegetTimes:int = 0;
		private var m_nMaxRetryTimes:int;
		
		private var m_Timer:Timer = null;
		private var m_Loader:flash.display.Loader = new flash.display.Loader();
		private var m_LoaderContext:flash.system.LoaderContext = new flash.system.LoaderContext();
		
		public function NetLoader()
		{
			super();	
		}
		
		private function AddLoaderEvent():void
		{
			if(m_Timer!=null)
			{
				m_Timer.addEventListener(TimerEvent.TIMER,OnOutTime);
			}
			
			m_Loader.contentLoaderInfo.addEventListener(Event.COMPLETE,OnDownOk);
			m_Loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,OnIOError);
        	m_Loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,OnSecurityError);
        	m_Loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,OnProgress);
		}
		
		private function RemoveLoaderEvent():void
		{
			if(m_Timer!=null)
			{
				m_Timer.removeEventListener(TimerEvent.TIMER,OnOutTime);
			}
			
			m_Loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,OnDownOk);
			m_Loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR,OnIOError);
        	m_Loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,OnSecurityError);
        	m_Loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,OnProgress);
		}
		
		public function DownLoad(url:String, target:String = TARGET_CHILD,retry:int = DEF_MAX_RET_TIMES,timeout:int = -1):void
		{
			m_nRegetTimes = 0;
			m_nMaxRetryTimes = retry;
			
			m_sDownUrl = SpLib.Net.URLResMgr.MakeUrl(url);
			
			if(timeout>0)
			{
				m_Timer = new Timer(timeout);
			}
			
			switch(target)
            {
			case NetLoader.TARGET_CHILD :
				m_LoaderContext.applicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
			break;
			case NetLoader.TARGET_SAME :
				m_LoaderContext.applicationDomain = ApplicationDomain.currentDomain;
			break;
			case NetLoader.TARGET_NEW :
				m_LoaderContext.applicationDomain = new ApplicationDomain();
			break;
            }

			AddLoaderEvent();
			Try();
		}

		private function Try():void
		{
			m_Loader.load(new URLRequest(m_sDownUrl),m_LoaderContext);
			
			if(m_Timer!=null)
			{
				m_Timer.reset();
				m_Timer.start();
			}
		}
		
		private function Retry():void
		{
			if(m_nRegetTimes++<m_nMaxRetryTimes)
			{
				Try();
			}
			else
			{
				RemoveLoaderEvent();
				dispatchEvent(new IOErrorEvent(IOErrorEvent.NETWORK_ERROR));
			}
		}
		
		private function OnIOError(event:IOErrorEvent):void
		{
			Retry();
		}
		
		private function OnSecurityError(event:SecurityErrorEvent):void
		{
			Retry();
		}
		
		private function OnOutTime(evt:TimerEvent):void
		{		
			Retry();
		}

		private function OnProgress(evt:ProgressEvent):void
		{
			m_nRegetTimes = 0;
			
			if(m_Timer!=null)
			{
				m_Timer.reset();
				m_Timer.start();
			}
			
			dispatchEvent(evt);
		}
		
		private function OnDownOk(evt:Event):void
		{		
			RemoveLoaderEvent();
			dispatchEvent(evt);
		}
	}
}